package com.koi.system.service.menu;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koi.common.ex.koi.YUtil;
import com.koi.common.satoken.KoiLoginUtil;
import com.koi.model.bo.element.CascaderLongBo;
import com.koi.model.bo.system.SysMenuBo;
import com.koi.model.vo.system.SysMenuVo;
import com.koi.plus.mapper.system.SysLoginUserMapper;
import com.koi.plus.mapper.system.SysMenuMapper;
import com.koi.pojo.system.SysLoginUser;
import com.koi.pojo.system.SysMenu;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author ･ᴗ･
 * @description [菜单权限表-服务实现层]
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    private final SysMenuMapper sysMenuMapper;

    private final SysLoginUserMapper sysLoginUserMapper;

    /**
     * @description [查询菜单]
     * @author ･ᴗ･
     */
    @Override
    public List<SysMenu> listSysMenu(SysMenuVo vo) {
        return sysMenuMapper.listSysMenu(vo);
    }

    /**
     * @description [生成当前用户所拥有菜单路由]
     * @author ･ᴗ･
     */
    @Override
    public List<SysMenuBo> generatorRouters() {
        // 1、根据用户ID查询用户信息
        SysLoginUser loginUser = sysLoginUserMapper.selectById(KoiLoginUtil.getUserId());
        YUtil.isTrue(ObjectUtils.isEmpty(loginUser), "请先进行登录");
        // 2、查询菜单数据
        if (loginUser != null && KoiLoginUtil.getIsKoiAdmin()) { // 超级管理员，全部菜单权限
            List<SysMenuBo> sysMenuBos = sysMenuMapper.listMenuAdmin();
            YUtil.isTrue(CollectionUtil.isEmpty(sysMenuBos), "菜单权限全部被删除，禁止登录");
            List<SysMenuBo> menuList = sysMenuBos.parallelStream().filter(x -> {
                LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SysMenu::getParentId, x.getMenuId());
                wrapper.last("limit 1");
                SysMenu menu = this.getOne(wrapper);
                if (ObjectUtil.isNotEmpty(menu)) {
                    x.setRedirect(menu.getPath());
                }
                return true;
            }).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(menuList)) {
                return menuList;
            } else {
                return Collections.emptyList();
            }
        } else {
            // 根据用户ID查询当前角色所拥有的菜单列表
            List<SysMenuBo> sysMenuBos = sysMenuMapper.listMenuByUserId(KoiLoginUtil.getUserId());
            YUtil.isTrue(CollectionUtil.isEmpty(sysMenuBos), "该用户角色未分配菜单权限，禁止登录");
            List<SysMenuBo> menuList = sysMenuBos.parallelStream().filter(x -> {
                LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SysMenu::getParentId, x.getMenuId());
                wrapper.last("limit 1");
                SysMenu menu = this.getOne(wrapper);
                if (ObjectUtil.isNotEmpty(menu)) {
                    x.setRedirect(menu.getPath());
                }
                return true;
            }).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(menuList)) {
                return menuList;
            } else {
                return Collections.emptyList();
            }
        }
    }

    /**
     * @description [菜单级联下拉框]
     * @author ･ᴗ･
     */
    @Override
    public List<CascaderLongBo> cascaderList() {
        return sysMenuMapper.cascaderList();
    }

    /**
     * @description [根据用户拥有的角色ID查询权限菜单]
     * @author ･ᴗ･
     */
    @Override
    public List<Long> listMenuIdsByRoleId(Long roleId) {
        // 菜单反选数据[菜单反选只注重子节点，父节点不用返回，子节点都有父节点自然会选中]
        List<SysMenu> menuList = sysMenuMapper.listMenuIdsByRoleId(roleId);
        if(CollectionUtils.isEmpty(menuList)){
            return Collections.emptyList();
        }
        // 剔除父节点数据
        List<SysMenu> collectMenuList = menuList.parallelStream().filter(x -> {
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysMenu::getParentId, x.getMenuId());
            long count = this.count(wrapper);
            return count == 0L;
        }).collect(Collectors.toList());
        // 反显数据
        if (CollectionUtil.isNotEmpty(collectMenuList)) {
            return collectMenuList.parallelStream().map(SysMenu::getMenuId).collect(Collectors.toList());
        } else {
            return Collections.emptyList();
        }
    }

    /**
     * @description [保存角色和菜单权限之间的关系]
     * @author ･ᴗ･
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveRoleMenu(Long roleId, List<Long> menuIds) {
        // 1、删除该角色拥有的权限
        sysMenuMapper.deleteMenuIdsByRoleId(roleId);
        if (menuIds.get(0) != -1) { // 取消当前角色所有权限，传递-1不进行保存操作
            // 2、保存菜单权限
            YUtil.isTrue(!sysMenuMapper.saveRoleMenu(roleId, menuIds), "分配失败，请重试");
        }
    }

}
